/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//		File Name		:		ObjectManager.cpp
//
//		Author			:		Vindicated Games
//            
//		Purpose			:		To encapsulate the functions and members of the ObjectManager
//
//		Dates			:		Written( Feb 15, 2011 ) by Vindicated Games		LastUpdate( April 12, 2011  ) by TunderCatz 
//	
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "VIN_ObjectManager.h"
#include "../Game Objects/CBaseObject.h"
#include "../Managers/ParticleManager.h"
#include "../Game Objects/CEnemy.h"
#include "../Game Objects/CButton.h"
#include "../Visual/VIN_BitMapFont.h"
#include "../Core/MessageSystem.h"
#include <algorithm>
#include "../Game States/CGamePlayState.h"
using std::sort;

VIN_ObjectManager* VIN_ObjectManager::m_pInstance = NULL;

VIN_ObjectManager::VIN_ObjectManager()
{
	m_pInstance = NULL;
	pPlayer = NULL;
	pHand = NULL;
}

VIN_ObjectManager::~VIN_ObjectManager()
{

}

bool VIN_ObjectManager::CheckCollision()
{
	bool check;

	//Check the Enemies to objects
	for(unsigned int i = 0; i < m_vEnemies.size(); i++)
	{
		for(unsigned int j = 0; j< m_vObjects.size(); j++)
		{
			check = m_vEnemies[i]->CheckCollision(m_vObjects[j]);

			if(check)
				continue;
		}
	}

	//Check the objects to Enemies 
	for(unsigned int i = 0; i < m_vObjects.size(); i++)
	{
		for(unsigned int j = 0; j< m_vEnemies.size(); j++)
		{
			check = m_vObjects[i]->CheckCollision(m_vEnemies[j]);

			if(check)
				continue;
		}
	}

	//Check the objects to objects 
	for(unsigned int i = 0; i < m_vObjects.size(); i++)
	{
		for(unsigned int j = 0; j< m_vObjects.size(); j++)
		{
			if(i!=j)
			{
				check = m_vObjects[i]->CheckCollision(m_vObjects[j]);
				
				if(check)
					continue;
			}
		}
	}

	//Check Player to Objects
	for(unsigned int j = 0; j< m_vObjects.size(); j++)
	{
		check = m_vObjects[j]->CheckCollision(pPlayer);

		if(check)
			continue;
	}



	//Check Player to Enemies
	for(unsigned int k = 0; k < m_vEnemies.size(); k++)
	{
		check = m_vEnemies[k]->CheckCollision(pPlayer);

		if(check)
			continue;
	}
	//Enemy to Player
	for(unsigned int k = 0; k < m_vEnemies.size(); k++)
	{
		if(!m_vEnemies.empty())
			check = pPlayer->CheckCollision(m_vEnemies[k]);

		if(check)
			continue;
	}

	//Enemy to Hand
	/*for(unsigned int i = 0; i < m_vEnemies.size(); i++)
	{
		if(!m_vEnemies.empty())
			check = pHand->CheckCollision(m_vEnemies[i]);
		if(check)
			continue;
	}*/

	//Check Player to Objects
	for(unsigned int i = 0; i< m_vObjects.size(); i++)
	{
		check = pPlayer->CheckCollision(m_vObjects[i]);

		if(check)
			continue;
	}

	//Check the Enemies to Enemies (Killing by smashing in air)
	for(unsigned int i = 0; i < m_vEnemies.size(); i++)
	{
		for(unsigned int j = 0; j< m_vEnemies.size(); j++)
		{
			if(i != j)
			{
				check = m_vEnemies[i]->CheckCollision(m_vEnemies[j]);
				if(check)
					continue;
			}
		}
	}
	return false;
}


//Loop through every list and Update and Render
void VIN_ObjectManager::UpdateObjects(float fElapsedTime)
{
	vector<CBaseObject*> deadlist;
	
		for (unsigned int i=0; i < m_vEnemies.size(); i++)
		{	
			CBaseObject* Enemy = (CBaseObject*)(m_vEnemies[i]);
			if( !((CBaseEnemy*)Enemy)->GetAlive() )
			{
				deadlist.push_back(Enemy);
				CGamePlayState::GetInstance()->GetPlayer()->SetCash( CGamePlayState::GetInstance()->GetPlayer()->GetCash() + 50 );
				continue;
			}
			m_vEnemies[i]->Update(fElapsedTime);
	}
	for (unsigned int i=0; i < deadlist.size(); i++)
	{
		RemoveObject(0, deadlist[i]);
	}

	//Player's List
	for (unsigned int i=0; i < m_vP_Objects.size(); i++)
		m_vP_Objects[i]->Update(fElapsedTime);

	for (unsigned int i=0; i < m_vObjects.size(); i++)
		m_vObjects[i]->Update(fElapsedTime);

	pPlayer->Update(fElapsedTime);
	//pHand->Update(fElapsedTime);

}

bool VIN_ObjectManager::InputObjects()
{
	if( pPlayer )
	{
		pPlayer->Input();
	}
	return true;
}

bool ZSort( IBaseInterface* obj1, IBaseInterface* obj2 )
{
	return ((CBaseObject*)obj1)->GetGroundPt() + ((CBaseObject*)obj1)->GetHeight() < ((CBaseObject*)obj2)->GetGroundPt() + ((CBaseObject*)obj2)->GetHeight();
	//return /*obj1->GetPosY() + */obj1->GetRect().bottom < obj2->GetRect().bottom;//obj2->GetPosY();
}
void VIN_ObjectManager::RenderObjects(void)
{
	vector<IBaseInterface*> CompiledList;

	//CompiledList.push_back(pPlayer);

	for (unsigned int i=0; i < m_vEnemies.size(); i++)
		CompiledList.push_back(m_vEnemies[i]);

	for (unsigned int i=0; i < m_vP_Objects.size(); i++)
		CompiledList.push_back(m_vP_Objects[i]);

	for (unsigned int i=0; i < m_vObjects.size(); i++)
		CompiledList.push_back(m_vObjects[i]);

	//CompiledList.push_back(pHand);

	if( !CGamePlayState::GetInstance()->GetLose()  && !CGamePlayState::GetInstance()->GetWin())
		pPlayer->Render();

	sort(CompiledList.begin(), CompiledList.end(), ZSort );

	if(CompiledList.size() > 0)
	{
		for( unsigned int j = 0; j < (CompiledList.size() - 1); j++ )
		{
			if(CompiledList[j]->GetType() == OBJ_BUTTON && ((CButton*)CompiledList[j])->GetButtonType() == BUTTON_ROCK && ((CButton*)CompiledList[j])->GetPrice() * 2 <= CGamePlayState::GetInstance()->GetPlayer()->GetCash() && CGamePlayState::GetInstance()->GetHand()->GetRockLevel() < 5)
			{
				CSGD_TextureManager::GetInstance()->Draw(MessageSystem::GetInstance()->GetStaticImageID(IMAGE_PIXEL),
					(int)((CButton*)CompiledList[j])->GetRect().left,(int)((CButton*)CompiledList[j])->GetRect().top, 
					(float)(((CButton*)CompiledList[j])->GetRect().right - ((CButton*)CompiledList[j])->GetRect().left),
					(float)(((CButton*)CompiledList[j])->GetRect().bottom - ((CButton*)CompiledList[j])->GetRect().top),
					0,0,0,0,D3DCOLOR_ARGB(150, 255,215,0));

				CompiledList[j]->Render();

				CSGD_TextureManager::GetInstance()->Draw(MessageSystem::GetInstance()->GetStaticImageID(IMAGE_PIXEL),
					(int)((CButton*)CompiledList[j])->GetRect().left,(int)((CButton*)CompiledList[j])->GetRect().top, 
					(float)(((CButton*)CompiledList[j])->GetRect().right - ((CButton*)CompiledList[j])->GetRect().left),
					(float)(((CButton*)CompiledList[j])->GetRect().bottom - ((CButton*)CompiledList[j])->GetRect().top),
					0,0,0,0,D3DCOLOR_ARGB(150, 255,215,0));
				CSGD_TextureManager::GetInstance()->Draw(MessageSystem::GetInstance()->GetStaticImageID(IMAGE_PIXEL),
					((CButton*)CompiledList[j])->GetRect().left + 5, 
					((CButton*)CompiledList[j])->GetRect().bottom + 45, 
					(float)(strlen("^^Right Click to Upgrade") * 10.0f),
					30,0,0,0,0, D3DCOLOR_ARGB(200,0,100,100));
				VIN_BitMapFont::GetInstance()->Render("^^",
					((CButton*)CompiledList[j])->GetRect().left + 10, 
					((CButton*)CompiledList[j])->GetRect().bottom + 45, 0.750f,
					D3DCOLOR_ARGB(255,255,64,32), MENUFONT);
				VIN_BitMapFont::GetInstance()->Render("  Right Click to Upgrade",
					((CButton*)CompiledList[j])->GetRect().left + 10, 
					((CButton*)CompiledList[j])->GetRect().bottom + 50, 0.750f,
					D3DCOLOR_ARGB(255,255,64,32), GAMEFONT);
			}
			else
			{				
				//ParticleManager::GetInstance()->Render();
				CompiledList[j]->Render();
			}
		}

		ParticleManager::GetInstance()->Render();
		CompiledList[CompiledList.size() - 1]->Render();
	}
	
	if(CompiledList.size() > 0)
	{
		//CompiledList[CompiledList.size() - 1]->Render();
		//CompiledList[CompiledList.size() - 1]->Render();

		for( unsigned int j = 0; j < (CompiledList.size()); j++ )
		{
			if(CompiledList[j]->GetType() == OBJ_BUTTON)
			{
				if(((CButton*)CompiledList[j])->GetShowPrice())
				{
					char Price[64];
					char Rock[64];
					if(((CButton*)CompiledList[j])->GetButtonType() != BUTTON_HAND && ((CButton*)CompiledList[j])->GetButtonType() != BUTTON_POISON && ((CButton*)CompiledList[j])->GetButtonType() != BUTTON_CASTLEUPGRADE && ((CButton*)CompiledList[j])->GetButtonType() != BUTTON_ARCHER )
						sprintf_s(Price, "Cost: $%d", ((CButton*)CompiledList[j])->GetPrice());
					else if(((CButton*)CompiledList[j])->GetButtonType() == BUTTON_CASTLEUPGRADE && CGamePlayState::GetInstance()->GetPlayer()->GetCastleLevel() < 3)
						sprintf_s(Price, "Upgrade: $%d", ((CButton*)CompiledList[j])->GetPrice());
					else if(((CButton*)CompiledList[j])->GetButtonType() == BUTTON_ARCHER)
					{
						if(CGamePlayState::GetInstance()->GetHand()->GetArcherLevel() < 10)
							sprintf_s(Price, "Cost: $%d", ((CButton*)CompiledList[j])->GetPrice());
						else
							sprintf_s(Price, "");
					}

					else
						sprintf_s(Price, "");

					if(((CButton*)CompiledList[j])->GetButtonType() == BUTTON_ROCK && ((CButton*)CompiledList[j])->GetPrice() * 2 <= CGamePlayState::GetInstance()->GetPlayer()->GetCash() && CGamePlayState::GetInstance()->GetHand()->GetRockLevel() < 5)
					{
						sprintf_s(Rock, "Upgrade: $%d", ((CButton*)CompiledList[j])->GetPrice() * 2);
						CSGD_TextureManager::GetInstance()->Draw(MessageSystem::GetInstance()->GetStaticImageID(IMAGE_PIXEL),CGamePlayState::GetInstance()->GetHand()->GetCursorBox().left - 75, CGamePlayState::GetInstance()->GetHand()->GetCursorBox().top + 25, (float)(strlen(Rock) * 13.0f)/*130*/,40,0,0,0,0, D3DCOLOR_ARGB(200,0,0,128));
						VIN_BitMapFont::GetInstance()->Render(Rock, CGamePlayState::GetInstance()->GetHand()->GetCursorBox().left - 65, CGamePlayState::GetInstance()->GetHand()->GetCursorBox().top + 35, 0.80f, D3DCOLOR_ARGB(255,255,32,32), MENUFONT);
					}

					CSGD_TextureManager::GetInstance()->Draw(MessageSystem::GetInstance()->GetStaticImageID(IMAGE_PIXEL),CGamePlayState::GetInstance()->GetHand()->GetCursorBox().left - 50, CGamePlayState::GetInstance()->GetHand()->GetCursorBox().top - 20, (float)(strlen(Price) * 13.0f)/*130*/,40,0,0,0,0, D3DCOLOR_ARGB(200,0,0,0));
					VIN_BitMapFont::GetInstance()->Render(Price, CGamePlayState::GetInstance()->GetHand()->GetCursorBox().left - 40, CGamePlayState::GetInstance()->GetHand()->GetCursorBox().top - 10, 0.80f, D3DCOLOR_ARGB(255,255,32,32), MENUFONT);
				}
			}
		}
	}
}

//check the type then add it to appropriate vector
void VIN_ObjectManager::AddObject(int ListToAdd, IBaseInterface* pObject)
{
	//check the type then add it to appropriate vector
	//Int is which of the lists you wish to add the object to
	// 0 = for Anything Enemy Related, 1 = for Player and Play related Objects, 2 = for any other Object
	//Check to see if object is good
	if( pObject == NULL )
		return;

	switch( ListToAdd )
	{
	case 0:
		{
			m_vEnemies.push_back(pObject);
			pObject->AddRef();
		}
		break;

	case 1:
		{
			m_vP_Objects.push_back(pObject);
			pObject->AddRef();
		}
		break;

	case 2:
		{
			m_vObjects.push_back(pObject);
			pObject->AddRef();
		}
		break;
	}

}
//check the type then remove it from appropriate vector
void VIN_ObjectManager::RemoveObject(int ListToRemove, IBaseInterface* pObject)
{
	//check the type then add it to appropriate vector
	//Int is which of the lists you wish to remove the object from
	// 0 = for Anything Enemy Related, 1 = for Player Projectiles, 2 = for any other Object

	if( pObject == NULL )
		return;

	switch(ListToRemove)
	{

	case 0:
		{
			for(vector<IBaseInterface*>::iterator iter = m_vEnemies.begin(); iter != m_vEnemies.end(); iter++)
			{

				if((*iter) == pObject )
				{
					//Remove my reference to this object.
					(*iter)->Release();

					//Remove the object from the list
					iter = m_vEnemies.erase(iter);
					break;
				}

			}
		}


		break;
	case 1:
		{

			for(vector<IBaseInterface*>::iterator iter = m_vP_Objects.begin(); iter != m_vP_Objects.end(); iter++)
			{

				if((*iter) == pObject )
				{
					//Remove my reference to this object.
					(*iter)->Release();

					//Remove the object from the list
					iter = m_vP_Objects.erase(iter);
					break;
				}
			}
		}
		break;
	case 2:
		{
			for(vector<IBaseInterface*>::iterator iter = m_vObjects.begin(); iter != m_vObjects.end(); iter++)
			{
				if((*iter) == pObject )
				{
					//Remove my reference to this object.
					(*iter)->Release();

					//Remove the object from the list
					iter = m_vObjects.erase(iter);
					break;
				}
			}
		}
		break;
	}





}
void VIN_ObjectManager::KillAll()
{
	for(int i = 0; i < (int)m_vEnemies.size();i++)
	{
		((CBaseEnemy*)m_vEnemies[i])->SetHP( ((CBaseEnemy*)m_vEnemies[i])->GetHP() - 9001);
	}
}


//Remove all Objects from everyList
void VIN_ObjectManager::RemoveAllObjects(void)
{
	//Enemy List
	if( GetNumOfObjectsEnemies() != 0 )
	{
		for( unsigned int i = 0; i < m_vEnemies.size(); i++ )
		{
			m_vEnemies[i]->Release();
		}

		m_vEnemies.clear();
	}

	//Player Projectile List

	if( GetNumOfObjectsPlayerProjectiles() != 0 )
	{
		for( unsigned int i = 0; i < m_vP_Objects.size(); i++ )
		{

			m_vP_Objects[i]->Release();
		}

		m_vP_Objects.clear();
	}



	//Object List
	if( GetNumOfObjects_Object() != 0 )
	{
		for( unsigned int i = 0; i < m_vObjects.size(); i++ )
		{

			m_vObjects[i]->Release();
		}
		m_vObjects.clear();
	}

}

VIN_ObjectManager*	VIN_ObjectManager::GetInstance()
{
	if( !m_pInstance )
	{
		m_pInstance = new VIN_ObjectManager();
	}
	return m_pInstance;
}

void VIN_ObjectManager::DeleteInstance()
{

	if(  m_pInstance )
	{
		delete m_pInstance;
		m_pInstance = NULL;
	}

}


void VIN_ObjectManager::ShutDown()
{
	if( m_pInstance )
	{
		DeleteInstance();
	}
}